package com._21cn.cms.article.utils;

import com._21cn.cms.article.entity.Article;
import com._21cn.cms.article.service.ArticleService;
import com._21cn.cms.common.Constants;
import com._21cn.cms.site.entity.Column;
import com._21cn.cms.site.service.ColumnCopyService;
import com._21cn.cms.template.utils.TemplateHelper;
import com._21cn.framework.utils.FileUtil;
import com.alibaba.fastjson.JSON;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * Created by Thinkpad on 2017/4/15.
 */
@Component("publishHelper")
public class PublishHelper {

    private SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MMdd/HH/");

    private LinkedBlockingQueue<Integer> regionQueue = new LinkedBlockingQueue<Integer>();
    private LinkedBlockingQueue<Integer> columnQueue = new LinkedBlockingQueue<Integer>();
    private LinkedBlockingQueue<Integer> channelQueue = new LinkedBlockingQueue<Integer>();

    private boolean keepRun = true;
    private final long UPDATE_QUEUE_CHECK_INTERVAL_TIME = 1 * 60L * 1000L; // 更新队列的检查间隔60秒

    @Autowired
    private ArticleHelper articleHelper;

    @Autowired
    private TemplateHelper templateHelper;

    @Autowired
    private ArticleService articleService;

    @Autowired
    private ColumnCopyService columnCopyService;

    @PostConstruct
    public void initGeneratePageThread() {
        startRegionThread();
        startColumnThread();
        startChannelThread();
    }

    private void startRegionThread() {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (keepRun) {
                    try {
                        Integer regionId = regionQueue.poll(UPDATE_QUEUE_CHECK_INTERVAL_TIME, TimeUnit.MILLISECONDS);
                        if (regionId != null) {
                            Thread.sleep(10000L);
                            templateHelper.generateRegionPage(regionId);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.setName("regionGenerateThread");
        t.start();
    }

    private void startColumnThread() {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (keepRun) {
                    try {
                        Integer columnId = columnQueue.poll(UPDATE_QUEUE_CHECK_INTERVAL_TIME, TimeUnit.MILLISECONDS);
                        if (columnId != null) {
                            templateHelper.generateColumnPage(columnId);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.setName("columnGenerateThread");
        t.start();
    }

    private void startChannelThread() {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (keepRun) {
                    try {
                        Integer channelId = channelQueue.poll(UPDATE_QUEUE_CHECK_INTERVAL_TIME * 10, TimeUnit.MILLISECONDS);
                        if (channelId != null) {
                            templateHelper.generateChannelPage(channelId);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.setName("channelGenerateThread");
        t.start();
    }

    public int addChannelTask(int channelId) {
        try {
            if (!channelQueue.contains(channelId))
                channelQueue.put(channelId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return channelQueue.size();
    }

    public int addColumnTask(int columnId) {
        try {
            if (!columnQueue.contains(columnId))
                columnQueue.put(columnId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return columnQueue.size();
    }

    public int addRelateTask(int columnId) {
        try {
            Column destColumn = this.columnCopyService.getDestColumn(Integer.valueOf(columnId));
            Integer descColumnId = destColumn.getId();
            if (!this.columnQueue.contains(descColumnId)) {
                this.columnQueue.put(descColumnId);
            }
            Integer channelId = destColumn.getChannelId();
            if (!this.channelQueue.contains(channelId))
                this.channelQueue.put(channelId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this.columnQueue.size();
    }

    public int addRegionTask(int regionId) {
        try {
            if (!regionQueue.contains(regionId))
                regionQueue.put(regionId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return regionQueue.size();
    }

    /**
     * 发布文章，生成json，删除缓存
     * @param article
     */
    public void publishArticle( Article article ){
        article = articleHelper.regulate4Show( article );
        generateArticleJsonFile(article);    // 生成json文件
        deleteCacheFile(article.getId());    // 删除文章缓存
    }

    public void deleteCacheFile(Integer articleId) {
        Article article = articleService.getById(articleId);
        String pcPath = templateHelper.getArticleStaticFolder(article, com._21cn.cms.article.Constants.CLIENT_CODE_PC);
        String wapPath = templateHelper.getArticleStaticFolder(article, com._21cn.cms.article.Constants.CLIENT_CODE_WAP);
        String appPath = templateHelper.getArticleStaticFolder(article, com._21cn.cms.article.Constants.CLIENT_CODE_APP);
        FileUtil.deleteDirectory(pcPath, true);
        FileUtil.deleteDirectory(wapPath, true);
        FileUtil.deleteDirectory(appPath, true);
    }

    public Article generateArticleJsonFile( Article article ) {     //  路径：/data/21cn/article/3gct.21cn.com/2016/
        String jsonPath = getJsonFilePath(article);
        File jsonFile = new File(jsonPath);
        if (!jsonFile.getParentFile().exists())
            jsonFile.getParentFile().mkdirs();
        try {
            FileUtils.write(jsonFile, JSON.toJSONString(article, true), "utf8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return article;
    }

    public String getJsonFilePath( Article article ){
        StringBuilder jsonPath = new StringBuilder(Constants.DEFAULT_FILE_PATH).append("/")
                .append(article.getSite().getCode()).append("/article/").append(article.getChannel().getHost())
                .append(sdf.format(article.getPublishTime())).append(article.getId()).append(".json");
        return jsonPath.toString();
    }

}
